package com.ruicar.afs.cloud.manage.common.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.csp.sentinel.util.StringUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruicar.afs.cloud.basic.api.dto.PrepaymentInfoManageDto;
import com.ruicar.afs.cloud.basic.api.fegin.info.BasicInfoFeign;
import com.ruicar.afs.cloud.common.core.constant.CommonConstants;
import com.ruicar.afs.cloud.common.core.enums.AfsEnumUtil;
import com.ruicar.afs.cloud.common.core.exception.AfsBaseException;
import com.ruicar.afs.cloud.common.core.query.QueryCondition;
import com.ruicar.afs.cloud.common.core.translog.service.GlobalTransService;
import com.ruicar.afs.cloud.common.core.util.IResponse;
import com.ruicar.afs.cloud.common.enums.ServiceNameEnum;
import com.ruicar.afs.cloud.common.enums.ToBasicSyncDataUrl;
import com.ruicar.afs.cloud.common.modules.contract.enums.*;
import com.ruicar.afs.cloud.common.util.EmptyUtils;
import com.ruicar.afs.cloud.common.vo.StaySettleVo;
import com.ruicar.afs.cloud.manage.api.dto.ImmunityDto;
import com.ruicar.afs.cloud.manage.api.dto.PrepaymentInfoDto;
import com.ruicar.afs.cloud.manage.api.dto.PrepaymentRecordDto;
import com.ruicar.afs.cloud.manage.api.feign.gateway.ContractGateWayCall;
import com.ruicar.afs.cloud.manage.common.condition.ManagePrepaymentApplyCondition;
import com.ruicar.afs.cloud.manage.common.condition.ManagePrepaymentQuotationCondition;
import com.ruicar.afs.cloud.manage.common.condition.SettleEarlyRecordQueryCondition;
import com.ruicar.afs.cloud.manage.common.entity.*;
import com.ruicar.afs.cloud.manage.common.service.*;
import com.ruicar.afs.cloud.manage.common.util.CreatCaseNoUtil;
import com.ruicar.afs.cloud.manage.common.vo.SettleEarlyRecordVo;
import com.ruicar.afs.cloud.manage.workflow.entity.WorkTaskCreatedInfo;
import com.ruicar.afs.cloud.manage.workflow.enums.NormalSubmitEnum;
import com.ruicar.afs.cloud.manage.workflow.enums.WorkflowTypeEnum;
import com.ruicar.afs.cloud.manage.workflow.processor.ApproveTaskProcessor;
import com.ruicar.afs.cloud.manage.workflow.processor.ContractWorkFlowSaveApproveInfoProcessor;
import com.ruicar.afs.cloud.manage.workflow.service.WorkTaskCreatedInfoService;
import com.ruicar.afs.cloud.manage.workflow.service.WorkflowSubmitService;
import com.ruicar.afs.cloud.manage.workflow.vo.TaskSubmitVO;
import com.ruicar.afs.cloud.workflow.api.dto.flowprocess.request.StartFlowRequest;
import com.ruicar.afs.cloud.workflow.gwt.service.WorkflowService;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.*;
import java.util.function.Function;

/**
 * @author: yaorui.zhang
 * @date: 2020年6月18日 18:05:25
 * @description: 待结清查询使用
 */
@Slf4j
@RestController
@AllArgsConstructor
@RequestMapping("/staySettle")
public class StaySettleController {

    private final ContractGateWayCall contractGateWayCall;
    private final ManagePrepaymentQuotationService managePrepaymentQuotationService;
    private final ManageCostExemptBillService manageCostExemptBillService;
    private final ManageCostExemptService manageCostExemptService;
    private final ManagePenaltyExemptService managePenaltyExemptService;
    private final ManagePrepaymentApplyService managePrepaymentApplyService;
    private final ContractWorkFlowSaveApproveInfoProcessor saveApproveInfoProcessor;
    private final WorkflowSubmitService workflowSubmitService;
    private final WorkflowService workflowService;
    private final WorkTaskCreatedInfoService workTaskCreatedInfoService;
    private final BasicInfoFeign basicInfoFeign;
    private final ApproveTaskProcessor approveTaskProcessor;
    private final ManageApplyRecordService manageApplyRecordService;
    private final GlobalTransService globalTransService;
    private final ComAttachementFileService comAttachementFileService;

    /**
     * 提前还款报价失效
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/prepaymentRecordInvalid")
    @ApiOperation(value = "提前还款报价失效")
    public IResponse prepaymentRecordInvalid(@RequestParam("contractNo") String contractNo) {
        //根据合同编号查询已经审核通过的申请
        ManagePrepaymentApply managePrepaymentApply = managePrepaymentApplyService.getOne((Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(ManagePrepaymentApply::getContractNo, contractNo)
                .eq(ManagePrepaymentApply::getApplyStatus, CaseStatusEnum.APPROVED)
        ));
        //状态置为失效
        managePrepaymentApply.setApplyStatus(CaseStatusEnum.INVALID);//申请失效
        managePrepaymentApply.setStatus(ValidOrInvalidEnum.invalid);//无效
        managePrepaymentApplyService.updateById(managePrepaymentApply);
        return IResponse.success("操作成功");
    }

    /**
     * 生成待扣款数据之前调用此方法进行提前还款的扣款操作
     *
     * @param
     * @return
     * @author ZC.GUO
     */
    @PostMapping(value = "/getPrepaymentRecordInfo")
    @ApiOperation(value = "查询提前还款的列表信息")
    public IResponse<List<PrepaymentInfoDto>> getPrepaymentRecordInfo() {
        List<PrepaymentInfoDto> prepaymentInfoDtoList = new ArrayList<>();
        /**  提起结清申请处于有效期内的记录 by ZC.GUO  **/
        List<ManagePrepaymentApply> prepaymentApplyList = managePrepaymentApplyService.list(Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(ManagePrepaymentApply::getApplyStatus, CaseStatusEnum.APPROVED)
                .eq(ManagePrepaymentApply::getDataSource, DataSourceEnum.icos)
        );
        if (EmptyUtils.isNotEmpty(prepaymentApplyList)) {
            for (ManagePrepaymentApply prepaymentApply : prepaymentApplyList) {
                ManagePrepaymentQuotation quotation = managePrepaymentQuotationService.getById(prepaymentApply.getQuotationId());

                PrepaymentInfoDto prepaymentInfoDto = new PrepaymentInfoDto();
                prepaymentInfoDto.setContractNo(prepaymentApply.getContractNo());
                prepaymentInfoDto.setReceivableAmount(quotation.getReceivableAmount());
                prepaymentInfoDto.setRepayDate(prepaymentApply.getRepayDate());
                prepaymentInfoDto.setRepayMode(prepaymentApply.getRepayMode());
                prepaymentInfoDto.setSourceTable(ManagePrepaymentQuotation.class.getAnnotation(TableName.class).value());
                prepaymentInfoDto.setSourceId(quotation.getId());
                prepaymentInfoDtoList.add(prepaymentInfoDto);
            }
        }
        return IResponse.success(prepaymentInfoDtoList);
    }

    @PostMapping(value = "/getPrepaymentRecordByContractNos")
    @ApiOperation(value = "根据合同号查询提前结清记录")
    public IResponse<List<PrepaymentRecordDto>> getPrepaymentRecordByContractNos(@RequestParam("contractNos") String contractNos) {
        List<PrepaymentRecordDto> prepaymentRecordDtoList = new ArrayList<>();

        List<String> contractNoList = Arrays.asList(contractNos.split(","));

        List<ManagePrepaymentApply> prepaymentApplyList = managePrepaymentApplyService.list(Wrappers.<ManagePrepaymentApply>query().lambda()
                .in(ManagePrepaymentApply::getContractNo, contractNoList)
        );
        if (EmptyUtils.isNotEmpty(prepaymentApplyList)) {
            prepaymentApplyList.forEach(prepaymentApply -> {
                PrepaymentRecordDto prepaymentRecordDto = new PrepaymentRecordDto();
                BeanUtils.copyProperties(prepaymentApply, prepaymentRecordDto);
                ManagePrepaymentQuotation prepaymentQuotation = managePrepaymentQuotationService.getById(prepaymentApply.getQuotationId());
                if (EmptyUtils.isNotEmpty(prepaymentQuotation)) {
                    prepaymentRecordDto.setUnpayedCaptial(prepaymentQuotation.getUnpayedCaptial());
                    prepaymentRecordDto.setInterestReceivable(prepaymentQuotation.getInterestReceivable());
                    prepaymentRecordDto.setAlreadyPeriods(prepaymentQuotation.getAlreadyPeriods());
                    prepaymentRecordDto.setReceivableAmount(prepaymentQuotation.getReceivableAmount());
                    prepaymentRecordDto.setPrepaymentCharge(prepaymentQuotation.getPrepaymentCharge());
                }
                prepaymentRecordDtoList.add(prepaymentRecordDto);
            });
        }
        return IResponse.success(prepaymentRecordDtoList);

    }

    @PostMapping(value = "/getPrepaymentInterestByContractNo")
    @ApiOperation(value = "根据合同号查询提前结清记录")
    public IResponse<BigDecimal> getPrepaymentInterestByContractNo(@RequestParam("contractNo") String contractNo) {
        ManagePrepaymentApply prepaymentApply = managePrepaymentApplyService.getOne(Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(ManagePrepaymentApply::getContractNo, contractNo)
                .eq(ManagePrepaymentApply::getApplyStatus, CaseStatusEnum.APPROVED)
                .eq(ManagePrepaymentApply::getDataSource, DataSourceEnum.icos)
        );
        if (EmptyUtils.isNotEmpty(prepaymentApply)) {
            ManagePrepaymentQuotation prepaymentQuotation = managePrepaymentQuotationService.getById(prepaymentApply.getQuotationId());
            return IResponse.success(prepaymentQuotation.getInterestReceivable());
        } else {
            return IResponse.fail("该合同无已生效的提前结清记录");
        }
    }

    @PostMapping(value = "/getStaySettleList")
    @ApiOperation(value = "多条件分页获取待结清任务池")
    public IResponse<List<ManagePrepaymentQuotation>> getStaySettleList(@RequestBody QueryCondition<ManagePrepaymentQuotationCondition> condition) {
        IPage<List<ManagePrepaymentQuotation>> list = managePrepaymentQuotationService.page(new Page(condition.getPageNumber(), condition.getPageSize()), (Wrappers.<ManagePrepaymentQuotation>query().lambda()
                .eq(StringUtil.isNotEmpty(condition.getCondition().getApplyNo()), ManagePrepaymentQuotation::getApplyNo, condition.getCondition().getApplyNo())//申请编号
                .eq(StringUtil.isNotEmpty(condition.getCondition().getContractNo()), ManagePrepaymentQuotation::getContractNo, condition.getCondition().getContractNo())//合同编号
                .like(StringUtil.isNotEmpty(condition.getCondition().getCustName()), ManagePrepaymentQuotation::getCustName, condition.getCondition().getCustName())//客户姓名
        ));
        return IResponse.success(list);
    }

    @PostMapping(value = "/saveStaySettle")
    @ApiOperation(value = "保存待结清任务池")
    public IResponse saveStaySettle(@RequestBody ManagePrepaymentQuotationCondition condition) {
        ManagePrepaymentQuotation managePrepaymentQuotation = new ManagePrepaymentQuotation();
        BeanUtils.copyProperties(condition, managePrepaymentQuotation); //属性赋值
        managePrepaymentQuotation.setCurrentContractStatus(condition.getContractStatus());
        managePrepaymentQuotationService.saveOrUpdate(managePrepaymentQuotation);
        //如果是微信端发起的申请，则自动调用提交方法
        if (condition.getBusinessSource() == BusinessSourceEnum.WE_CHAT) {
            this.trailLaunchProcess(condition);
        }
        condition.setQuotationId(managePrepaymentQuotation.getId());
        return IResponse.success(managePrepaymentQuotation);
    }

    @PostMapping(value = "/getStaySettleDetailById/{id}")
    @ApiOperation(value = "根据ID获取详情")
    public IResponse<ManagePrepaymentQuotation> getStaySettleDetailById(@PathVariable String id) {
        ManagePrepaymentQuotation managePrepaymentQuotation = managePrepaymentQuotationService.getById(id);
        return IResponse.success(managePrepaymentQuotation);
    }

    @PostMapping(value = "/getStaySettleDetailByApplyNo/{applyNo}")
    @ApiOperation(value = "根据申请编号获取详情")
    public IResponse<ManagePrepaymentQuotation> getStaySettleDetailByApplyNo(@PathVariable String applyNo) {
        ManagePrepaymentQuotation managePrepaymentQuotation = managePrepaymentQuotationService.getOne(Wrappers.<ManagePrepaymentQuotation>query().lambda()
                        .eq(ManagePrepaymentQuotation::getApplyNo, applyNo)
                        .orderByDesc(ManagePrepaymentQuotation::getCreateTime)
                , false
        );
        return IResponse.success(managePrepaymentQuotation);
    }

    @ApiOperation(value = "生效豁免单查询")
    @PostMapping("/queryManageCostExemptBill")
    public IResponse queryManageCostExemptBill(@RequestBody ImmunityDto dto) {
        ManageCostExemptBill manageCostExemptBill = manageCostExemptBillService.getOne(Wrappers.<ManageCostExemptBill>query().lambda()
                        .eq(ManageCostExemptBill::getContractNo, dto.getContractNo())
                        .eq(ManageCostExemptBill::getStatus, CostExemptBillStatusEnum.effect)
                , false
        );
        return IResponse.success(manageCostExemptBill);
    }

    @ApiOperation(value = "费用豁免信息表查询")
    @PostMapping("/queryExemptAmountDetail")
    public IResponse queryExemptAmountDetail(@RequestBody QueryCondition<ManagePrepaymentQuotationCondition> condition) {
        IPage<List<ManageCostExempt>> manageCostExempt = manageCostExemptService.page(new Page(condition.getPageNumber(), condition.getPageSize()), Wrappers.<ManageCostExempt>query().lambda()
                .eq(ManageCostExempt::getContractNo, condition.getCondition().getContractNo())
                .ge(EmptyUtils.isNotEmpty(condition.getCondition().getCalculateTime()), ManageCostExempt::getEndDate, condition.getCondition().getCalculateTime())
                .eq(ManageCostExempt::getStatus, ProcessStatusEnum.approved)
        );
        return IResponse.success(manageCostExempt);
    }

    @ApiOperation(value = "单笔罚息豁免信息查询")
    @PostMapping("/queryExemptOverdueInterestDetail")
    public IResponse queryExemptOverdueInterestDetail(@RequestBody QueryCondition<ManagePrepaymentQuotationCondition> condition) {
        IPage<List<ManagePenaltyExempt>> managePenaltyExempt = managePenaltyExemptService.page(new Page(condition.getPageNumber(), condition.getPageSize()), Wrappers.<ManagePenaltyExempt>query().lambda()
                .eq(ManagePenaltyExempt::getContractNo, condition.getCondition().getContractNo())
                .ge(EmptyUtils.isNotEmpty(condition.getCondition().getCalculateTime()), ManagePenaltyExempt::getEndDate, condition.getCondition().getCalculateTime())
                .eq(ManagePenaltyExempt::getProcessStatus, ProcessStatusEnum.approved)
        );
        return IResponse.success(managePenaltyExempt);
    }

    @PostMapping(value = "/getManagePrepaymentApply")
    @ApiOperation(value = "多条件分页获取待结清任务池")
    public IResponse getManagePrepaymentApply(@RequestBody QueryCondition<ManagePrepaymentApplyCondition> condition) {
        //开始时间
        Date prepaymentRequestTimeStart = null;
        Date prepaymentRequestTimeEnd = null;
        if (condition.getCondition().getPrepaymentRequestTimeQuery() != null && condition.getCondition().getPrepaymentRequestTimeQuery().length > 0
                && StringUtil.isNotEmpty(condition.getCondition().getPrepaymentRequestTimeQuery()[0]) && StringUtil.isNotEmpty(condition.getCondition().getPrepaymentRequestTimeQuery()[1])) {
            prepaymentRequestTimeStart = DateUtil.parse(condition.getCondition().getPrepaymentRequestTimeQuery()[0]);
            prepaymentRequestTimeEnd = DateUtil.offsetDay(DateUtil.parse(condition.getCondition().getPrepaymentRequestTimeQuery()[1]), 1);
        }
        //结束时间
        Date prepaymentApprovedTimeQueryStart = null;
        Date prepaymentApprovedTimeQueryEnd = null;
        if (condition.getCondition().getPrepaymentApprovedTimeQuery() != null && condition.getCondition().getPrepaymentApprovedTimeQuery().length > 0
                && StringUtil.isNotEmpty(condition.getCondition().getPrepaymentApprovedTimeQuery()[0]) && StringUtil.isNotEmpty(condition.getCondition().getPrepaymentApprovedTimeQuery()[1])) {
            prepaymentApprovedTimeQueryStart = DateUtil.parse(condition.getCondition().getPrepaymentApprovedTimeQuery()[0]);
            prepaymentApprovedTimeQueryEnd = DateUtil.offsetDay(DateUtil.parse(condition.getCondition().getPrepaymentApprovedTimeQuery()[1]), 1);
        }

        IPage list = managePrepaymentApplyService.page(new Page(condition.getPageNumber(), condition.getPageSize()), (Wrappers.<ManagePrepaymentApply>query().lambda()
                .eq(StringUtil.isNotEmpty(condition.getCondition().getApplyNo()), ManagePrepaymentApply::getApplyNo, condition.getCondition().getApplyNo())//申请编号
                .eq(StringUtil.isNotEmpty(condition.getCondition().getContractNo()), ManagePrepaymentApply::getContractNo, condition.getCondition().getContractNo())//合同编号
                .like(StringUtil.isNotEmpty(condition.getCondition().getCustName()), ManagePrepaymentApply::getCustName, condition.getCondition().getCustName())//客户姓名
                .eq(condition.getCondition().getProcessStatus() != null, ManagePrepaymentApply::getProcessStatus, condition.getCondition().getProcessStatus())//处理状态
                .eq(condition.getCondition().getBusinessSource() != null, ManagePrepaymentApply::getBusinessSource, condition.getCondition().getBusinessSource())//案件来源
                .eq(condition.getCondition().getRepayMode() != null, ManagePrepaymentApply::getRepayMode, condition.getCondition().getRepayMode())//还款方式
                .eq(condition.getCondition().getCollectionStatus() != null, ManagePrepaymentApply::getCollectionStatus, condition.getCondition().getCollectionStatus())//收款状态
                .ge(prepaymentRequestTimeStart != null, ManagePrepaymentApply::getPrepaymentRequestTime, prepaymentRequestTimeStart)//开始时间起
                .lt(prepaymentRequestTimeEnd != null, ManagePrepaymentApply::getPrepaymentRequestTime, prepaymentRequestTimeEnd)//开始时间止
                .ge(prepaymentApprovedTimeQueryStart != null, ManagePrepaymentApply::getPrepaymentApprovedTime, prepaymentApprovedTimeQueryStart)//结束时间起
                .lt(prepaymentApprovedTimeQueryEnd != null, ManagePrepaymentApply::getPrepaymentApprovedTime, prepaymentApprovedTimeQueryEnd)//结束时间止
        ));
        return new IResponse().setData(list.setRecords(approveTaskProcessor.handle(list.getRecords())));
    }

    @PostMapping(value = "/getValidPrepaymentApply")
    @ApiOperation(value = "多条件分页获取生效状态的提前结清记录")
    public IResponse<IPage<SettleEarlyRecordVo>> getValidPrepaymentApply(@RequestBody SettleEarlyRecordQueryCondition condition) {
        Page page = new Page(condition.getPageNumber(), condition.getPageSize());
        IPage<ManagePrepaymentApply> list = managePrepaymentApplyService.page(page, Wrappers.<ManagePrepaymentApply>query().lambda()
                .like(EmptyUtils.isNotEmpty(condition.getContractNo()), ManagePrepaymentApply::getContractNo, condition.getContractNo())
                .like(EmptyUtils.isNotEmpty(condition.getCustName()), ManagePrepaymentApply::getCustName, condition.getCustName())
                .like(EmptyUtils.isNotEmpty(condition.getCertNo()), ManagePrepaymentApply::getCertNo, condition.getCertNo())
                .like(EmptyUtils.isNotEmpty(condition.getApplyNo()), ManagePrepaymentApply::getApplyNo, condition.getApplyNo())
                .like(EmptyUtils.isNotEmpty(condition.getCaseNo()), ManagePrepaymentApply::getCaseNo, condition.getCaseNo())
                .eq(ManagePrepaymentApply::getStatus, ValidOrInvalidEnum.valid)
                .eq(ManagePrepaymentApply::getApplyStatus, CaseStatusEnum.APPROVED)
                .ne(ManagePrepaymentApply::getCollectionStatus, CollectionStatusEnum.SUCCESS_COLLECTION)
        );
        return IResponse.success(list.convert(new Function<ManagePrepaymentApply, SettleEarlyRecordVo>() {

            @Override
            public SettleEarlyRecordVo apply(ManagePrepaymentApply apply) {

                SettleEarlyRecordVo settleEarlyRecordVo = new SettleEarlyRecordVo();
                settleEarlyRecordVo.setApplyNo(apply.getApplyNo());
                settleEarlyRecordVo.setCaseNo(apply.getCaseNo());
                settleEarlyRecordVo.setContractNo(apply.getContractNo());
                settleEarlyRecordVo.setCustName(apply.getCustName());
                settleEarlyRecordVo.setPrepaymentRequestTime(apply.getPrepaymentRequestTime());
                settleEarlyRecordVo.setContractStatus(apply.getCurrentContractStatus());
                settleEarlyRecordVo.setDataSource(apply.getBusinessSource());
                settleEarlyRecordVo.setId(apply.getId());

                ManagePrepaymentQuotation quotation = managePrepaymentQuotationService.getById(apply.getQuotationId());
                settleEarlyRecordVo.setReceivableAmount(quotation.getReceivableAmount());
                settleEarlyRecordVo.setRepayDate(quotation.getExecuteTime());
                settleEarlyRecordVo.setIsOverDate(String.valueOf(Calendar.getInstance().getTime().after(DateUtil.endOfDay(settleEarlyRecordVo.getRepayDate()))));
                if (ReceiptSourceTypeEnum.bankDeduct.equals(apply.getRepayMode())) {
                    /**  接口查询扣款指令 by ZC.GUO  **/
                    IResponse<ValidOrInvalidEnum> response = basicInfoFeign.getPrepaymentDebitOrderValidation(settleEarlyRecordVo.getContractNo());
                    if (CommonConstants.SUCCESS.equals(response.getCode())) {
                        settleEarlyRecordVo.setDebitOrderStatus(response.getData());
                    }
                } else {
                    settleEarlyRecordVo.setDebitOrderStatus(ValidOrInvalidEnum.invalid);
                }

                return settleEarlyRecordVo;
            }
        }));

    }

    @PostMapping(value = "/getApplyInfoById")
    @ApiOperation(value = "根据id获取其他信息")
    public IResponse<SettleEarlyRecordVo> getApplyInfoById(@RequestBody SettleEarlyRecordQueryCondition condition) {
        ManagePrepaymentApply apply = managePrepaymentApplyService.getById(condition.getId());
        SettleEarlyRecordVo settleEarlyRecordVo = new SettleEarlyRecordVo();
        if (EmptyUtils.isNotEmpty(apply)) {
            settleEarlyRecordVo.setApplyNo(apply.getApplyNo());
            settleEarlyRecordVo.setCaseNo(apply.getCaseNo());
            settleEarlyRecordVo.setContractNo(apply.getContractNo());
            settleEarlyRecordVo.setCustName(apply.getCustName());
            settleEarlyRecordVo.setPrepaymentRequestTime(apply.getPrepaymentRequestTime());
            settleEarlyRecordVo.setContractStatus(apply.getCurrentContractStatus());
            settleEarlyRecordVo.setDataSource(apply.getBusinessSource());
            settleEarlyRecordVo.setId(apply.getId());

            ManagePrepaymentQuotation quotation = managePrepaymentQuotationService.getById(apply.getQuotationId());
            settleEarlyRecordVo.setReceivableAmount(quotation.getReceivableAmount());
            settleEarlyRecordVo.setRepayDate(quotation.getExecuteTime());
            if (ReceiptSourceTypeEnum.bankDeduct.equals(apply.getRepayMode())) {
                /**  接口查询扣款指令 by ZC.GUO  **/
                IResponse<ValidOrInvalidEnum> response = basicInfoFeign.getPrepaymentDebitOrderValidation(settleEarlyRecordVo.getContractNo());
                if (CommonConstants.SUCCESS.equals(response.getCode())) {
                    settleEarlyRecordVo.setDebitOrderStatus(response.getData());
                }
            } else {
                settleEarlyRecordVo.setDebitOrderStatus(ValidOrInvalidEnum.invalid);
            }
        }
        return IResponse.success(settleEarlyRecordVo);

    }

    @PostMapping(value = "/delManagePrepaymentApplyById/{id}")
    @ApiOperation(value = "根据id删除数据")
    public IResponse<ManagePrepaymentApply> delManagePrepaymentApplyById(@PathVariable String id) {
        ManagePrepaymentApply managePrepaymentApply = managePrepaymentApplyService.getById(id);
        managePrepaymentQuotationService.removeById(managePrepaymentApply.getQuotationId());//删除报价单
        managePrepaymentApplyService.removeById(id);//删除提前结清申请
        return IResponse.success(true);
    }

    @PostMapping(value = "/getManagePrepaymentApplyById/{id}")
    @ApiOperation(value = "根据id获取详情")
    public IResponse<ManagePrepaymentApply> getManagePrepaymentApplyById(@PathVariable String id) {
        ManagePrepaymentApply managePrepaymentApply = managePrepaymentApplyService.getById(id);
        return IResponse.success(managePrepaymentApply);
    }

    @PostMapping(value = "/saveManagePrepaymentApply")
    @ApiOperation(value = "保存待结清任务池")
    public IResponse saveManagePrepaymentApply(@RequestBody ManagePrepaymentQuotationCondition condition) {

        //合同是否满6期
        YesOrNoEnum isSixPeriod = YesOrNoEnum.no;
        if (condition.getAlreadyPeriods() > 6) {
            isSixPeriod = YesOrNoEnum.yes;
        }
        //保存提前结清报价单
        ManagePrepaymentQuotation managePrepaymentQuotation = new ManagePrepaymentQuotation();
        BeanUtils.copyProperties(condition, managePrepaymentQuotation); //属性赋值
        managePrepaymentQuotation.setCurrentContractStatus(condition.getContractStatus());//合同状态
        managePrepaymentQuotation.setId(condition.getQuotationId());//试算单ID
        managePrepaymentQuotation.setIsSixPeriod(isSixPeriod);//合同是否满6期
        managePrepaymentQuotationService.saveOrUpdate(managePrepaymentQuotation);
        //豁免费用大于0时，证明豁免为是
        YesOrNoEnum isExempt = YesOrNoEnum.no;
        if (condition.getExemptAmount().compareTo(BigDecimal.ZERO) > 0) {
            isExempt = YesOrNoEnum.yes;
        }
        //保存提前结清申请表
        ManagePrepaymentApply managePrepaymentApply = new ManagePrepaymentApply();
        BeanUtils.copyProperties(condition, managePrepaymentApply);//属性赋值
        managePrepaymentApply.setPrepaymentRequestTime(condition.getCalculateTime());//申请时间
        managePrepaymentApply.setCurrentContractStatus(condition.getContractStatus());//合同状态
        managePrepaymentApply.setIsSixPeriod(isSixPeriod);//合同是否满6期
        managePrepaymentApply.setQuotationId(managePrepaymentQuotation.getId());//报价单ID
        managePrepaymentApply.setId(condition.getApplyId());//申请ID
        managePrepaymentApply.setIsExempt(isExempt);//是否豁免
        managePrepaymentApply.setProcessStatus(ProcessStatusEnum.draft);//草稿
        managePrepaymentApply.setApplyStatus(CaseStatusEnum.NOT_SUBMIT);//未提交
        managePrepaymentApply.setStatus(ValidOrInvalidEnum.valid);//有效
        managePrepaymentApply.setCollectionStatus(CollectionStatusEnum.NO_COLLECTION);//未收款
        managePrepaymentApplyService.saveOrUpdate(managePrepaymentApply);
        condition.setApplyId(managePrepaymentApply.getId());

        return IResponse.success(managePrepaymentApply);
    }

    @SneakyThrows
    @PostMapping(value = "/trailLaunchProcess")
    @ApiOperation(value = "发起流程")
    @Transactional
    public IResponse trailLaunchProcess(@RequestBody ManagePrepaymentQuotationCondition condition) {
        //根据ID查询申请表
        ManagePrepaymentApply managePrepaymentApply = managePrepaymentApplyService.getById(condition.getApplyId());
        // 生成案件编号
        managePrepaymentApply.setCaseNo(CreatCaseNoUtil.GeneratorCaseNo(ContractBusinessEnum.advanceSettle));
        managePrepaymentApply.setPrepaymentRequestTime(DateUtil.date());//案件开始时间
        managePrepaymentApply.setApplyStatus(CaseStatusEnum.UNDER_REVIEW);//审核中

        //附件塞入案件编号
        comAttachementFileService.saveFile(managePrepaymentApply.getContractNo(), managePrepaymentApply.getCaseNo(), ContractBusinessEnum.advanceSettle.name());
        //满六期且银行代扣
        if (YesOrNoEnum.yes.equals(managePrepaymentApply.getIsSixPeriod())
                && ReceiptSourceTypeEnum.bankDeduct.equals(managePrepaymentApply.getRepayMode())) {
            managePrepaymentApply.setProcessStatus(ProcessStatusEnum.approved);//审核结束
            managePrepaymentApply.setPrepaymentApprovedTime(DateUtil.date());//案件结束时间
            managePrepaymentApply.setApplyStatus(CaseStatusEnum.APPROVED);//审核通过

            //查询是否存在豁免中的流程
            this.judje(managePrepaymentApply.getContractNo());

        } else {
            managePrepaymentApply.setProcessStatus(ProcessStatusEnum.underReview);//审核中
        }
        managePrepaymentApplyService.updateById(managePrepaymentApply);
        //报价单启用
        ManagePrepaymentQuotation managePrepaymentQuotation = managePrepaymentQuotationService.getById(managePrepaymentApply.getQuotationId());
        managePrepaymentQuotation.setIsUsed(YesOrNoEnum.yes);//启用
        managePrepaymentQuotation.setOtherCost(condition.getOtherCost());
        managePrepaymentQuotationService.updateById(managePrepaymentQuotation);
        //保存待办任务记录
        saveApproveInfoProcessor.saveApproveInfo(managePrepaymentApply, ContractBusinessEnum.advanceSettle, CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.ADVANCE_SETTLE);
        //首节点，保存审批记录共用公用方法
        saveApproveInfoProcessor.saveApproveRecord(managePrepaymentApply, ContractBusinessEnum.advanceSettle);
        //发起流程
        StartFlowRequest startFlowRequest = new StartFlowRequest();
        startFlowRequest.setAfsFlowKey(AfsEnumUtil.key(WorkflowTypeEnum.EARLY_SETTLEMENT));
        startFlowRequest.setBizDataId(String.valueOf(managePrepaymentApply.getId()));
        startFlowRequest.setFlowName((StringUtils.isEmpty(managePrepaymentApply.getContractNo()) ? "" : (managePrepaymentApply.getContractNo()) + "-") + AfsEnumUtil.desc(WorkflowTypeEnum.EARLY_SETTLEMENT));
        String json = JSONObject.toJSONString(managePrepaymentApply);
        JSONObject cancelJson = JSONObject.parseObject(json);
        workflowService.startWorkFlow(startFlowRequest, cancelJson);
        this.callPaymentBack(managePrepaymentApply);

        //费用表生成提前终止费用
        StaySettleVo staySettleVo = new StaySettleVo();
        staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
        staySettleVo.setCostAmt(managePrepaymentQuotation.getPrepaymentCharge());
        staySettleVo.setEndDate(managePrepaymentApply.getEndDate());
        IResponse<Boolean> response = globalTransService.post(
                String.valueOf(managePrepaymentApply.getId()),
                AfsEnumUtil.key(ServiceNameEnum.BASIC),
                AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_SET_PREPAYMENT_CHARGE),
                staySettleVo,
                new TypeReference<Boolean>() {
                }
        );
        if (CommonConstants.FAIL.equals(response.getCode())) {
            throw new AfsBaseException("提前还款手续费结果数据推送至basic服务失败，请重试！");
        }

        return IResponse.success("发起流程成功！");
    }

    @SneakyThrows
    @PostMapping(value = "/trailSubmitProcess")
    @ApiOperation(value = "提交流程")
    @Transactional
    public IResponse trailSubmitProcess(@RequestBody ManagePrepaymentQuotationCondition condition) {

        //根据ID查询申请表
        ManagePrepaymentApply managePrepaymentApply = managePrepaymentApplyService.getById(condition.getApplyId());
        //报价单启用
        ManagePrepaymentQuotation managePrepaymentQuotation = managePrepaymentQuotationService.getById(managePrepaymentApply.getQuotationId());
        managePrepaymentQuotation.setIsUsed(YesOrNoEnum.yes);//启用
        managePrepaymentQuotation.setOtherCost(condition.getOtherCost());
        managePrepaymentQuotationService.updateById(managePrepaymentQuotation);
        WorkTaskCreatedInfo workTaskCreatedInfo = workTaskCreatedInfoService.getOne(Wrappers.<WorkTaskCreatedInfo>query().lambda()
                        .eq(WorkTaskCreatedInfo::getBizDataId, condition.getApplyId().toString())
                        .orderByDesc(WorkTaskCreatedInfo::getCreateTime)
                , false
        );
        //更新处理状态
        if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_CHECK_FINAL).equals(condition.getApprovalOperating())) {

            if ("endOne".equals(workTaskCreatedInfo.getTaskMemo())) {//发起人直接提交
                managePrepaymentApply.setProcessStatus(ProcessStatusEnum.approved);
                managePrepaymentApply.setPrepaymentApprovedTime(DateUtil.date());//案件结束时间
                managePrepaymentApply.setApplyStatus(CaseStatusEnum.APPROVED);//审核通过
                //查询是否存在豁免中的流程
                this.judje(managePrepaymentApply.getContractNo());
                //保存待办任务记录
                saveApproveInfoProcessor.saveApproveInfo(managePrepaymentApply, ContractBusinessEnum.advanceSettle, CaseStatusEnum.APPROVED, BusinessUrlEnum.ADVANCE_SETTLE);
            } else if ("endTwo".equals(workTaskCreatedInfo.getTaskMemo())
                    && YesOrNoEnum.yes.equals(managePrepaymentApply.getIsExempt())) {//豁免
                managePrepaymentApply.setProcessStatus(ProcessStatusEnum.approved);
                managePrepaymentApply.setPrepaymentApprovedTime(DateUtil.date());//案件结束时间
                managePrepaymentApply.setApplyStatus(CaseStatusEnum.APPROVED);//审核通过
                //查询是否存在豁免中的流程
                this.judje(managePrepaymentApply.getContractNo());
                //保存待办任务记录
                saveApproveInfoProcessor.saveApproveInfo(managePrepaymentApply, ContractBusinessEnum.advanceSettle, CaseStatusEnum.APPROVED, BusinessUrlEnum.ADVANCE_SETTLE);
                //豁免单费用冲抵
                StaySettleVo staySettleVo = new StaySettleVo();
                staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
                staySettleVo.setExemptBillCost(condition.getExemptBillCost());
                IResponse<Boolean> response = globalTransService.post(
                        String.valueOf(managePrepaymentApply.getId()),
                        AfsEnumUtil.key(ServiceNameEnum.BASIC),
                        AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_SET_EXEMPTBILL_MITIGATE),
                        staySettleVo,
                        new TypeReference<Boolean>() {
                        }
                );
                if (CommonConstants.FAIL.equals(response.getCode())) {
                    throw new AfsBaseException("提前还款手续费结果数据推送至basic服务失败，请重试！");
                }
            } else {
                managePrepaymentApply.setProcessStatus(ProcessStatusEnum.underReview);
                //保存待办任务记录
                saveApproveInfoProcessor.saveApproveInfo(managePrepaymentApply, ContractBusinessEnum.advanceSettle, CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.ADVANCE_SETTLE);
                if ("endTwo".equals(workTaskCreatedInfo.getTaskMemo())) {
                    //豁免单费用冲抵
                    StaySettleVo staySettleVo = new StaySettleVo();
                    staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
                    staySettleVo.setExemptBillCost(condition.getExemptBillCost());
                    IResponse<Boolean> response = globalTransService.post(
                            String.valueOf(managePrepaymentApply.getId()),
                            AfsEnumUtil.key(ServiceNameEnum.BASIC),
                            AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_SET_EXEMPTBILL_MITIGATE),
                            staySettleVo,
                            new TypeReference<Boolean>() {
                            }
                    );
                    if (CommonConstants.FAIL.equals(response.getCode())) {
                        throw new AfsBaseException("提前还款手续费结果数据推送至basic服务失败，请重试！");
                    }
                } else if ("exemptBill".equals(workTaskCreatedInfo.getTaskMemo())) {
                    //豁免单费用冲抵
                    StaySettleVo staySettleVo = new StaySettleVo();
                    staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
                    staySettleVo.setExemptBillCost(condition.getExemptBillCost());
                    IResponse<Boolean> response = globalTransService.post(
                            String.valueOf(managePrepaymentApply.getId()),
                            AfsEnumUtil.key(ServiceNameEnum.BASIC),
                            AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_SET_EXEMPTBILL_MITIGATE),
                            staySettleVo,
                            new TypeReference<Boolean>() {
                            }
                    );
                    if (CommonConstants.FAIL.equals(response.getCode())) {
                        throw new AfsBaseException("提前还款手续费结果数据推送至basic服务失败，请重试！");
                    }
                }
            }
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SUGGEST_REJECT_FINAL).equals(condition.getApprovalOperating())) {
            managePrepaymentApply.setPrepaymentApprovedTime(DateUtil.date());//案件结束时间
            managePrepaymentApply.setProcessStatus(ProcessStatusEnum.refuse);
            managePrepaymentApply.setApplyStatus(CaseStatusEnum.REFUSE);//审核通过
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(managePrepaymentApply, ContractBusinessEnum.advanceSettle, CaseStatusEnum.REFUSE, BusinessUrlEnum.ADVANCE_SETTLE);
            if (!"endTwo".equals(workTaskCreatedInfo.getTaskMemo())) {
                //豁免单费用冲抵撤销
                StaySettleVo staySettleVo = new StaySettleVo();
                staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
                staySettleVo.setExemptBillCost(condition.getExemptBillCost());
                IResponse<Boolean> response = globalTransService.post(
                        String.valueOf(managePrepaymentApply.getId()),
                        AfsEnumUtil.key(ServiceNameEnum.BASIC),
                        AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_DEL_EXEMPTBILL_MITIGATE),
                        staySettleVo,
                        new TypeReference<Boolean>() {
                        }
                );
                if (CommonConstants.FAIL.equals(response.getCode())) {
                    throw new AfsBaseException("提前还款手续费结果数据推送至basic服务失败，请重试！");
                }
            } else if (!"exemptBill".equals(workTaskCreatedInfo.getTaskMemo())) {
                //豁免单费用冲抵撤销
                StaySettleVo staySettleVo = new StaySettleVo();
                staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
                staySettleVo.setExemptBillCost(condition.getExemptBillCost());
                IResponse<Boolean> response = globalTransService.post(
                        String.valueOf(managePrepaymentApply.getId()),
                        AfsEnumUtil.key(ServiceNameEnum.BASIC),
                        AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_DEL_EXEMPTBILL_MITIGATE),
                        staySettleVo,
                        new TypeReference<Boolean>() {
                        }
                );
                if (CommonConstants.FAIL.equals(response.getCode())) {
                    throw new AfsBaseException("提前还款手续费结果数据推送至basic服务失败，请重试！");
                }
            }
            //费用表生成提前终止费用
            StaySettleVo staySettleVo = new StaySettleVo();
            staySettleVo.setContractNo(managePrepaymentApply.getContractNo());
            IResponse<Boolean> response = globalTransService.post(
                    String.valueOf(managePrepaymentApply.getId()),
                    AfsEnumUtil.key(ServiceNameEnum.BASIC),
                    AfsEnumUtil.key(ToBasicSyncDataUrl.SYNC_DEL_PREPAYMENT_CHARGE),
                    staySettleVo,
                    new TypeReference<Boolean>() {
                    }
            );
        } else if (AfsEnumUtil.key(NormalSubmitEnum.SEND_BACK).equals(condition.getApprovalOperating())) {
            //案件结束时间
            managePrepaymentApply.setPrepaymentApprovedTime(DateUtil.date());
            managePrepaymentApply.setProcessStatus(ProcessStatusEnum.toBeRepaired);
            //保存待办任务记录
            saveApproveInfoProcessor.saveApproveInfo(managePrepaymentApply, ContractBusinessEnum.advanceSettle, CaseStatusEnum.UNDER_REVIEW, BusinessUrlEnum.ADVANCE_SETTLE);
        }
        managePrepaymentApplyService.updateById(managePrepaymentApply);

        //流程审批
        TaskSubmitVO vo = new TaskSubmitVO();
        String json = JSONObject.toJSONString(managePrepaymentApply);
        JSONObject cancelJson = JSONObject.parseObject(json);
        vo.setBizData(cancelJson);
        vo.setApprovalOperating(condition.getApprovalOperating());
        vo.setApprovalOpinion(condition.getApprovalOpinion());
        vo.setReasonType(condition.getReasonType());
        workflowSubmitService.submit(vo);
        this.callPaymentBack(managePrepaymentApply);
        return IResponse.success("流程提交成功！");
    }

    @Transactional
    @PostMapping(value = "/staySettleSubmitToCms")
    @ApiOperation(value = "提前结清操作，供接口聚合cms使用")
    public IResponse staySettleSubmitToCms(@RequestBody ManagePrepaymentQuotationCondition condition) {
        //通过合同的gateway聚合接口获取客户信息
        IResponse response = contractGateWayCall.mainInfofindByContractNo(condition.getContractNo());
        //转换JSONObject，直接取值，这里注意::: 如果聚合接口某个字段没有配置，则可能取到空字符串""
        cn.hutool.json.JSONObject custInfo = JSONUtil.parseObj(response.getData());
        String custName = custInfo.getStr("custName");
        condition.setCustName(custName);
        //调用试算结果保存
        IResponse iResponse2 = this.saveStaySettle(condition);
        //保存提前结清申请数据
        IResponse iResponse1 = this.saveManagePrepaymentApply(condition);
        //发起提前结清流程
        IResponse iResponse = this.trailLaunchProcess(condition);
        if (iResponse.getCode().equals("0000") && iResponse1.getCode().equals("0000") && iResponse2.getCode().equals("0000")) {
            return new IResponse().setData("保存成功");
        } else {
            return new IResponse().fail("提交失败，请重试！");
        }
    }

    //掉用扣款的结果，是否有正在扣款中的数据
    public Boolean callPaymentBack(ManagePrepaymentApply managePrepaymentApply) {
        //审核通过并且，约定扣款日等于当天，则调用扣款接口
        if (managePrepaymentApply.getApplyStatus().equals(CaseStatusEnum.APPROVED) && DateUtil.today().equals(managePrepaymentApply.getRepayDate())) {
            PrepaymentInfoManageDto prepaymentInfoManageDto = new PrepaymentInfoManageDto();
            prepaymentInfoManageDto.setContractNo(managePrepaymentApply.getContractNo());
            prepaymentInfoManageDto.setRepayDate(managePrepaymentApply.getRepayDate());
            prepaymentInfoManageDto.setReceivableAmount(managePrepaymentApply.getReceivableAmount());
            prepaymentInfoManageDto.setSourceId(managePrepaymentApply.getId());
            prepaymentInfoManageDto.setSourceTable("ManagePrepaymentApply");
            prepaymentInfoManageDto.setRepayMode(managePrepaymentApply.getRepayMode());
            basicInfoFeign.debitForPrepaymentImmediately(prepaymentInfoManageDto);
        }
        return true;
    }

    //查询是否存在豁免中的流程
    public void judje(String contractNo) {
        //查询是否存在豁免流程记录
        List<ManageApplyRecord> manageApplyRecordList = manageApplyRecordService.list(Wrappers.<ManageApplyRecord>query().lambda()
                .eq(ManageApplyRecord::getContractNo, contractNo)
                .eq(ManageApplyRecord::getCaseStatus, CaseStatusEnum.UNDER_REVIEW)
                .and(wraper -> wraper
                        .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.costExemptBill)
                        .or()
                        .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.exemptTypes)
                        .or()
                        .eq(ManageApplyRecord::getContractBusiness, ContractBusinessEnum.costExempt)
                )
        );
        if (manageApplyRecordList != null && manageApplyRecordList.size() > 0) {
            Assert.isTrue(false, "请先完成豁免流程！");
        }
    }

}
